﻿using System;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using D3D10Scene;
using System.Windows.Input;

namespace D3DImageTest
{
    public partial class Window1 : Window
    {
        private D3DImageEx m_d3DImageEx;
        private D3DImageEx m_d3DImageExGI;
        private D3D10TestScene m_d3D10Scene;
        Int64 average_ms;
        System.Diagnostics.Stopwatch timer;

        D3D9_Creator m_creator;

        public Window1()
        {
            InitializeComponent();
            Loaded += Window1_Loaded;
            Closing += new System.ComponentModel.CancelEventHandler(Window1_Closing);
            SizeChanged += new SizeChangedEventHandler(Window1_SizeChanged);
            average_ms = 0;
        }

        void ChangeSize(Double width, Double height)
        {        
            if (m_d3D10Scene != null)
	        {
                m_d3D10Scene.ChangeSize((int)width, (int)height);
                m_d3DImageEx.SetBackBufferEx(D3DResourceTypeEx.ID3D11Texture2D, m_d3D10Scene.GetRenderTarget());
	        }

        }

        void Window1_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            ChangeSize(e.NewSize.Width, e.NewSize.Height);
        }

        void Window1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            m_d3D10Scene.Release();
        }

        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            /* Create a new D3DImageEx class */
            m_creator = new D3D9_Creator();
            m_creator.InitD3D9();
            D3DImageEx.InitD3D9(m_creator.D3D9, m_creator.D3D9_Device);
            m_d3DImageEx = new D3DImageEx();
            m_d3DImageExGI = new D3DImageEx();
            timer = new System.Diagnostics.Stopwatch();
            
            /* Set our image's source to our D3DImage9Ex */
            d3dScene.Source = m_d3DImageEx;
            d3dSceneGI.Source = m_d3DImageExGI;

            Keyboard.Focus(dockPanel1);

            try
            {
                IntPtr hWnd = IntPtr.Zero;

                /* Create a new D3DTest scene */
                m_d3D10Scene = new D3D10TestScene(hWnd, (int)dockPanel1.ActualWidth, (int)dockPanel1.ActualHeight);

                ChangeSize(dockPanel1.ActualWidth, dockPanel1.ActualHeight);

                /* Set the backbuffer, which is a ID3D10Texture2D pointer */
                m_d3DImageEx.SetBackBufferEx(D3DResourceTypeEx.ID3D11Texture2D, m_d3D10Scene.GetRenderTarget());
                m_d3DImageExGI.SetBackBufferEx(D3DResourceTypeEx.ID3D11Texture2D, m_d3D10Scene.GetRenderTargetGI());

                CompositionTarget.Rendering += CompositionTarget_Rendering;
            }
            catch (System.Exception)
            {
            }

        }

         
        /// <summary>
        /// Invalidates entire D3DImage area
        /// </summary>
        private void InvalidateD3DImage(D3DImageEx d3d_image)
        {
            d3d_image.Lock();
            d3d_image.AddDirtyRect(new Int32Rect()
            {
                X = 0,
                Y = 0,
                Height = d3d_image.PixelHeight,
                Width = d3d_image.PixelWidth
            });
            d3d_image.Unlock();
        }

        private void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            /* Render D3D10 test scene */
            m_d3D10Scene.Render();

            /* Invalidate our D3DImage */
            InvalidateD3DImage(m_d3DImageEx);
            InvalidateD3DImage(m_d3DImageExGI);
            timer.Stop();
            average_ms = (average_ms * 9 + timer.ElapsedMilliseconds)/10;
            timer.Restart();
            counter.Content = "msPF:";
            counter.Content += average_ms.ToString();
            counter.Content += " ms";

            float x, y, z;

            unsafe
            {
                m_d3D10Scene.get_camera_pos(&x, &y, &z);
            }

            camera_pos.Content = "(" + x.ToString() + "," + y.ToString() + "," + z.ToString() + ")";
            pixels_visible.Content = m_d3D10Scene.get_visible_pixels();
        }

        private void open_file(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
            ofd.Filter = "Data Sources (*.dae, *.fbx)|*.dae*;*.fbx|All Files|*.*";

            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string filePath = ofd.FileName;
                string safeFilePath = ofd.SafeFileName;
                m_d3D10Scene.AddFile(filePath);
            }
        }

        private void d3dScene_KeyEvent(object sender, System.Windows.Input.KeyEventArgs e) { m_d3D10Scene.OnInput((D3D10Scene.InputEvent)KeyInterop.VirtualKeyFromKey(e.Key), e.IsDown); }

        private void d3dScene_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Point pos = e.GetPosition(this);
            m_d3D10Scene.SetMousePos((int)pos.X, (int)pos.Y);
        }

        private void DecimalUpDown_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (m_d3D10Scene != null)
            {
                m_d3D10Scene.SetCameraSpeed(System.Decimal.ToSingle((decimal)e.NewValue));
            }
        }

        private void d3dScene_MouseEvent(object sender, MouseButtonEventArgs e)
        {
            if (e.ButtonState == MouseButtonState.Pressed)
            {
                Keyboard.Focus(d3dScene);
            }

            m_d3D10Scene.OnInput(e.ChangedButton == MouseButton.Left ?   D3D10Scene.InputEvent.IK_LBUTTON :
                                 e.ChangedButton == MouseButton.Middle ? D3D10Scene.InputEvent.IK_MBUTTON :
                                                                         D3D10Scene.InputEvent.IK_RBUTTON,
                                 e.ButtonState == MouseButtonState.Pressed);
        }

        private void GI_Create_Click(object sender, RoutedEventArgs e)
        {
            m_d3D10Scene.create_gi();
        }

    }
}
